/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pig.pigpen.editor.editparts;

import java.beans.PropertyChangeEvent;
import java.util.LinkedList;
import java.util.List;

import org.apache.pig.pigpen.editor.model.Operator;
import org.apache.pig.pigpen.editor.policies.OperatorComponentEditPolicy;
import org.apache.pig.pigpen.editor.policies.OperatorDirectEditPolicy;
import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.requests.DirectEditRequest;
import org.eclipse.gef.tools.DirectEditManager;
import org.eclipse.jface.viewers.TextCellEditor;

public class OperatorEditPart extends PropertyAwarePart implements NodeEditPart {

    protected DirectEditManager manager;
    // private DirectEditManager manager;

    private List<DirectEditManager> managers;

    @Override
    public void setModel(Object model) {
        super.setModel(model);
        ((Operator) model).setEditPart(this);
    }

    @Override
    protected IFigure createFigure() {
        OperatorFigure fig = new OperatorFigure();
        updateFigure(fig);
        return fig;
    }

    private void updateFigure(OperatorFigure fig) {
        Operator op = (Operator) getModel();

        fig.setName(op.getName());
        fig.setText(op.getText());
        // fig.setError(op.getError());
        fig.setAlias(op.getAlias());
        fig.setExdata(op.getExdata());
        fig.setError(op.getError());
    }

    @Override
    protected void createEditPolicies() {
        installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE,
                new OperatorDirectEditPolicy());
        installEditPolicy(EditPolicy.COMPONENT_ROLE,
                new OperatorComponentEditPolicy());
    }

    protected List getModelSourceConnections() {
        Operator op = (Operator) getModel();
        return op.getOutputs();
    }

    protected List getModelTargetConnections() {
        Operator op = (Operator) getModel();
        return op.getInputs();
    }

    protected void refreshVisuals() {
        QueryEditPart query = (QueryEditPart) getParent();
        OperatorFigure fig = (OperatorFigure) getFigure();
        updateFigure(fig);

        Point location = fig.getLocation();
        Rectangle constraint = new Rectangle(location.x, location.y, -1, -1);
        query.setLayoutConstraint(this, fig, constraint);
    }

    public ConnectionAnchor getSourceConnectionAnchor(
            ConnectionEditPart connection) {
        return new ChopboxAnchor(getFigure());
    }

    public ConnectionAnchor getSourceConnectionAnchor(Request request) {
        return new ChopboxAnchor(getFigure());
    }

    public ConnectionAnchor getTargetConnectionAnchor(
            ConnectionEditPart connection) {
        return new ChopboxAnchor(getFigure());
    }

    public ConnectionAnchor getTargetConnectionAnchor(Request request) {
        return new ChopboxAnchor(getFigure());
    }

    public void propertyChange(PropertyChangeEvent evt) {
        super.propertyChange(evt);

        String property = evt.getPropertyName();

        if (Operator.TEXT.equals(property)) {
            commitTextChange();
        } else if (Operator.ERROR.equals(property)) {
            commitErrorChange();
        } else if (Operator.EXDATA.equals(property)) {
            commitExdataChange();
        } else if (Operator.NAME.equals(property)) {
            commitNameChange();
        } else if (Operator.ALIAS.equals(property)) {
            commitAliasChange();
        }
    }

    public Operator getModel() {
        return (Operator) super.getModel();
    }

    public void performRequest(Request request) {
        if (request.getType() == RequestConstants.REQ_DIRECT_EDIT) {
            if (request instanceof DirectEditRequest
                    && !directEditHitTest(((DirectEditRequest) request)
                            .getLocation().getCopy()))
                return;
            performDirectEdit();
        }
    }

    private boolean directEditHitTest(Point requestLoc) {
        IFigure figure = getFigure();
        figure.translateToRelative(requestLoc);
        return figure.containsPoint(requestLoc);
    }

    protected void performDirectEdit() {
        if (manager == null) {
            Label label = getFigure().getTextLabel();
            manager = new ExtendedDirectEditManager(this, TextCellEditor.class,
                    new LabelCellEditorLocator(label), label);
        }

        manager.show();
    }

    /*
     * protected void performDirectEdit() { if(managers == null) { managers =
     * new LinkedList<DirectEditManager>(); for(Label label :
     * getFigure().getTextLabels()) { manager = new
     * ExtendedDirectEditManager(this, TextCellEditor.class, new
     * LabelCellEditorLocator(label), label); managers.add(manager); } }
     * 
     * for(DirectEditManager m : managers) { m.show(); } }
     */

    /**
     * Sets the width of the line when selected
     */
    public void setSelected(int value) {
        super.setSelected(value);
        EditableFigure operatorFigure = (EditableFigure) getFigure();
        operatorFigure.setSelected(value != EditPart.SELECTED_NONE);
        operatorFigure.repaint();
    }

    public void handleTextChange(String text) {
        getFigure().setTextVisible(false);
    }

    public void commitTextChange() {
        getFigure().setText(getModel().getText());
    }

    public void commitErrorChange() {
        getFigure().setError(getModel().getError());
    }

    public void commitExdataChange() {
        getFigure().setExdata(getModel().getExdata());
    }

    public void commitNameChange() {
        getFigure().setName(getModel().getName());
    }

    public void commitAliasChange() {
        getFigure().setAlias(getModel().getAlias());
    }

    public void revertTextChange(String oldValue) {
        getFigure().setTextVisible(true);
    }

    public OperatorFigure getFigure() {
        return (OperatorFigure) super.getFigure();
    }
}
